QuickOPC User's Guide and Reference
OPC DA Optimizer
Extensions > Integrated Extensions > OPC DA Optimizer
In This Topic

The OPC DA Optimizer improves performance of certain OPC "Classic" Data Access operations. It is implemented as configurable plug-in on each EasyDAClient object instance. The plug-in is included and enabled by default, so that you do not have write any additional code in order to make use of its functionality.

QuickOPC also performs various optimizations on the lower level of OPC communication. The extension described here operates on higher level and only provides a specific supplementary optimization.

The optimizer can perform multiple optimizations, described below. Most optimizations work individually, but some only provide good results when combined with other optimizations.

The various optimizations performed by the OPC DA Optimizer are done on and for a specific EasyDAClient instance only. If multiple instances are used, the internal state that the optimizations may maintain is not shared. Some optimizations (such as Request Chunking, Request Merging, Parameter Restricting, and Parameter Bucketing) do not maintain state, and in this respect, the discussion is irrelevant for them. Other optimizations (such as Subscription Blending, Item Caching, or Auto-Subscribing) do maintain an internal state, and whether or not they are shared may have influence on the performance of the application. Generally, such optimizations would perform better if they have "shared" knowledge (state).

Use a common EasyDAClient instance for code that wants to allow sharing of the state used by the optimizations.

Request Chunking

A general rule of thumb for efficient OPC communication is to group the individual operations and perform them in larger groups (see Use multiple-operation methods instead of looping). There can be, however, a limit to that approach as well. Some servers have implementation limits that prevent them from fulfilling operations that contain too many requests at once. Also, there may be timeouts at various levels that can cause problems, as such operations take longer. Perhaps most importantly, though, when making subscriptions, many OPC servers will start delivering data change notifications only after all requests in the large operation are processed.

If, in case of subscription requests, the large operation is split into smaller ones, such OPC server gets a change to start delivering data change notification for the requests it has already processed, which means that your application will receive first change sooner (although, conversely, the whole subscription process may take a bit longer).

The OPC DA Optimizer performs requests chunking (i.e. splitting the very large operations into smaller ones) for you. By default, it is enabled to be in effect on all OPC operations. Because of its main purpose (to speed up delivery of data change notifications with large Subscribe operations), the default chunk size for Subscribe and Unsubscribe operations is smaller than for other operations such as Read or Write.

Following piece of code shows how to access parameters that allow you to influence the request chunking:

Set the chunk size for OPC DA SubscribeItem operations to 5000
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.RequestChunkingParameters.SubscribeItemsChunkSize = 5000;

Chunk size parameters are available for each particular type of operation. Setting the chunk size for an operation to zero disables request chunking for that operation.

Request chunking can be fully disabled as follows:

Disable OPC DA request chunking
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableRequestChunking = false;

Request Merging

If an OPC operation that works on multiple items or properties is called, and some of its arguments are identical to others, the requests with identical arguments can be merged into one. For example, it makes little sense to Read the same item from the same server, with the same read parameters, multiple times in the same call. The Read can be performed just once, and the results cloned and copied over where they belong.

You may ask why somebody would write such a "dumb" code that unnecessarily performs the same thing multiple times. And indeed, in many applications, the code you are writing will by itself assures that nothing like that can ever happen. But, in other applications, the arguments to OPC operations are quite dynamic, and can be specified by the end user (and even multiple users), read from a file etc., and in such cases you lose control over what the argument values precisely will be.

The OPC DA Optimizer performs request merging for you. By default, it is enabled to be in effect on all Read, Write and GetProperty operations that have identical arguments (except for the State property which may differ, because it does not influence the actual OPC operation).

Request merging can be fully disabled as follows:

Disable OPC DA request merging
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableRequestMerging = false;

Parameter Restricting

Certain operation parameter values can create unnecessary or unusual load on the OPC server. A typical example of that would be a very fast requested update rate. The parameter restricting optimization coerces certain parameters to reasonable limits, to prevent "dangerous" requests.

The parameter restricting currently affects following parameters:

Following piece of code shows how to access parameters that allow you to influence the parameter restricting:

Set the fastest update rate to 500 milliseconds
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.ParameterRestrictingParameters.SlowestUpdateRate = 500;

Parameter restricting can be fully disabled as follows:

Disable OPC DA parameter restricting
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableParameterRestricting = false;

Parameter Bucketing

The parameter bucketing optimization modifies some parameters to the OPC operations so that their values, if they are similar, are coerced into a single value, forming larger "buckets". This helps to perform the operation more efficiently.

For example, let's say that your program wants to subscribe to two OPC items, the first with requested update rate 1050 milliseconds, and the second with requested update rate of 1100 milliseconds. Normally, this would require two OPC Groups ("subscriptions") to be created in the OPC server, one for each requested update rate. The update rates are, however, quite close together, and actually, a single OPC Group would do. With parameter bucketing (in its default configuration), both these update rates (actually, any update rates between 1000 and 1467 milliseconds) will fall into a single "bucket", with update rate of 1000 milliseconds, and a single OPC Group with this update rate will be created for them. Your program may receive the value changes somewhat faster than requested, though - but not much.

The OPC DA Optimizer performs parameter bucketing for you. It is enabled by default. Currently, parameter bucketing is in effect for subscriptions only, and works as follows:

Following piece of code shows how to access parameters that allow you to influence the parameter bucketing:

Set the number of update rate buckets per decade to 24
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.ParameterBucketingParameters.UpdateRateBucketsPerDecade = 24;

Parameter bucketing can be fully disabled as follows:

Disable OPC DA parameter bucketing
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableParameterBucketing = false;
It is recommended that you keep the Parameter Bucketing optimization enabled, if you enable the Auto-Subscribing optimization. Without Parameter Bucketing, the Auto-Subscribing optimization may create unnecessary high number of OPC groups in the server.

Subscription Blending

When your code subscribes to the same OPC item multiple times, the Subscription Blending optimization can sometimes establish just a single subscription on the OPC level (or, a lower number of subscriptions what you have subscribed). For example, if precisely the same OPC group parameters (requested update rate, percent deadband, and locale) are used with multiple subscriptions to the same item, there is no need for the client to create multiple OPC Item objects in the OPC server - a single OPC Item is sufficient.

In slightly more complex scenarios, the OPC group parameters might be different, but some might be "better" (semantically, always provide more data) than others. If, for example, your code subscribes to the same OPC item twice, with the only difference that the requested update rate is 1000 milliseconds with one subscription and 2000 milliseconds with the other subscription, it is possible to reduce the load on the OPC server by simply using the requested update rate of 1000 milliseconds. Your second subscription, which has requested the update rate of 2000 milliseconds, will receive data updates possibly faster (more often) than requested, but in most scenarios that causes no harm.

The percent deadband in the OPC group parameters is compared and treated similarly. The locale (LCID) in the OPC group parameters, however, must equal precisely, otherwise the subscription blending cannot be put into effect.

You may ask whether Parameter Bucketing cannot, at least in some cases, fulfill the same task as Subscription Blending. For example, with default Parameter Bucketing, instead of two subscriptions with requested update rates 1000 and 1050 milliseconds, only the one with requested update rate 1000 milliseconds will be used.

There is, however, a crucial difference between the Subscription Blending and Parameter Bucketing: The Subscription Blending works on the same items only, and on the OPC-DA level, helps to prevent multiple additions of the same OPC Item into OPC Groups in the OPC Server. As such, it can lower the number of OPC Item objects requested by the client in the OPC Server, and consequently, number of OPC Group objects can also be reduced sometimes.

The Parameter Bucketing (for subscriptions), on the other hand, works on the OPC group parameters that can be (and usually are) for different OPC Items. It can lower the number of OPC Group objects requested by the client in the OPC Server, but it does not directly influence the number of OPC Item objects requested.

Subscription blending can be fully disabled as follows:

Disable OPC DA subscription blending
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableSubscriptionBlending = false;

Item Caching

With item caching, if QuickOPC has data for some item available from some previous operation, it will satisfy the Read request for the item using the data from its internal cache, without even contacting the target OPC server for it.

The item data that gets stored into the internal QuickOPC cache can come from other Read requests, or from item change notifications that result from Subscribe requests.

Read requests that specify "device" as their data source are not affected by Item Caching, and are always passed through for processing by lower layers.

Read requests that specify "by value age" or "cache" as their data source are satisfied either from the internal QuickOPC cache (this is sometimes referred to as reading "from memory", for distinction from the OPC server cache), or are passed through to lower layers, depending on whether cached data with requested value age is available or not.

For its operation, Item Caching does not use the timestamps that are part of OPC data. Instead, time points measured on the client side, and information such as item update rates (in Subscriptions) and maximum value age (in Reads) is used to make the caching decisions.

Item caching can be fully disabled as follows:

Disable OPC DA item caching
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableItemCaching = false;
You should keep the Item Caching optimization enabled, if you enable the Auto-Subscribing optimization. Without Item Caching, in some situations, the benefits of Auto-Subscribing optimization would be severely limited.

Auto-Subscribing

The auto-subscribing optimization attempts to provide better performance of repeated Reads of the same item by creating a subscription for that item. With the subscription, the subsequent Reads can then be satisfied more efficiently, with data available from the cache (which is filled by data collection made for the subscription). The repeated Read pattern is common in certain types of applications, such as Web applications or Web services which need to provide data based on incoming requests over which they have no control. In some cases, repeated Reads of the same item can also be sign of sub-optimal coding, and even in that case the auto-subscribing optimization may help (even though we would recommend to rewrite the code using Subscriptions, if possible).

The subscription is automatically created only after some number of repeated Reads is detected, modified later if needed, and is removed if the repeated Reads stop coming for some time. The parameters of the subscriptions are determined using factors such as the requested value age of the data in the Reads, and the frequency of the incoming Read requests. Obviously, without having upfront knowledge about the Read requests and their pattern, QuickOPC cannot know for sure what are the right parameters for the subscription, and when precisely the subscription should be created and when removed. All of this is determined dynamically, based on the observed usage patterns, and using intelligence and heuristics that are built into the auto-subscribing optimization. You should test how the optimization works for you in your specific case, and if needed, tweak the various parameters to achieve the desired result.

The main factor that influences the calculated update rate of the automatically created subscription is the effective value age requested in the Reads. The effective value age is 0 when Device data source is used, Infinite (-1) when Cache data source is used, or it is a specific value from the ValueAge Property if ByValueAge data source is used. For example, if all incoming Read requests use the value age of 1000 milliseconds, the automatically created subscription will be based on that. The update rate of the subscription will be somewhat faster, e.g. 900 milliseconds, in order to account for fluctuations in the timing of subscription updates.

When the specified effective value age is too low (e.g. 0 - for Device), the Read request does not contribute to the considerations made by the logic inside the auto-subscribing optimization. This is because it is impossible (in case of Device) or impractical (in case of non-zero, but very low valeu ages) to set up a subscription that would fill the cache with values needed for subsequent Reads. Similarly, when the specified effective value age is too low (e.g. several days), the Read request is ignored as well, because the "cost" of keeping the additional subscription would outweigh its benefits.

By default, the auto-subscribing optimization is turned off (in order to prevent creation of unexpected subscriptions in applications that are unaware of it). Auto-subscribing can be enabled as follows:

Enable OPC DA auto-subscribing
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableAutoSubscribing = true;

In order to allow shortening of the above code, QuickOPC also contains an extension method, TryEnableAutoSubscribingOptimization, which allows you to achieve the same effect simply like this:

Shorter code to enable the OPC DA auto-subscribing
Copy Code
client.TryEnableAutoSubscribingOptimization();

As described earlier, it is suggested that you use a common EasyDAClient Class instance to make benefit of shared optimization state. Also, it is recommended that you keep the Parameter Bucketing and Item Caching optimization turned on, if you use the Auto-subscribing optimization.

Server Database

CLSID from ProgID Resolution

When the OPC server is specified using its ProgID (in the server descriptor), the software has to first resolve the symbolic ProgID to a numeric CLSID (a globally unique identifier). This is done by searching through the registry, or using the OPCEnum service. This operation can take considerable time, especially when the OPC server is located remotely, and the network connection is slow. The time needed to resolve the ProgID to the CLSID slows down the connection operation. In addition, if the remote registry is not accessible, or OPCEnum is not properly installed, the ProgID resolution may fail and thus prevent the connection to the OPC server, even though the server might be present and operational.

QuickOPC contains a built-in database of some common OPC servers, and their ProgIDs and corresponding CLSIDs. This ProgID database optimization detects the ProgIDs of server that exist in the database, and quickly and efficiently transforms them to their CLSIDs right away, without a need to search through the registry or invoke OPCEnum.

Server Category Restriction

When the server database has information about server categories supported by the particular server, it can restrict the server categories allowed in the server descriptor for the operation. The connection to the server can thus be streamlined and made more effective.

Enabling and Disabling

The server database optimization is turned on by default. It can be disabled as follows:

Disable OPC DA request merging
Copy Code
DAOptimizerPluginParameters optimizerPluginParameters =
    client.InstanceParameters.PluginConfigurations.Find<DAOptimizerPluginParameters>();
if (!(optimizerPluginParameters is null))
    optimizerPluginParameters.EnableServerDatabase = false;

 

See Also